﻿module game.battle.enemies.missile;

import game.battle.enemies.base;

import game.battle.projectiles.fireprojectiles;

final class Missile : Base
{
private:
    Sprite mSprite;
    scalar_t mDir = 0;
    int mHealth = 1;
    int mTicksRemaining = 250;
public:
    static immutable scalar_t acceleration = 1;
    static immutable scalar_t deceleration = acceleration / 2;
    static immutable scalar_t rotAcceleration = div(1,100);
    static immutable scalar_t rotDeceleration = rotAcceleration / 2;
    static immutable rot_t    rotAccelerationV = rot_t(cos(rotAcceleration), sin(rotAcceleration));
    static immutable rot_t    rotDecelerationV = rot_t(cos(rotDeceleration), sin(rotDeceleration));
    static immutable scalar_t maxRotSpeed = div(1,40);
    static immutable rot_t    maxRotSpeedV = rot_t(cos(maxRotSpeed), sin(maxRotSpeed));
    static immutable scalar_t maxSpeed = 13;
    static immutable maxSpeedSquared = maxSpeed * maxSpeed;
    
    static immutable scalarw_t radius = 6;
    static immutable radiusSq = radius * radius;

    @property auto health() const pure nothrow { return mHealth; }
    @property void health(int h) pure nothrow { mHealth = h; }
    
    @property bool up()    const pure nothrow { return true; }
    @property bool down()  const pure nothrow { return false; }
    @property bool left()  const pure nothrow { return mDir > 0; }
    @property bool right() const pure nothrow { return mDir < 0; }
    
    this(BattleScene w)
    {
        super(w);
        mSprite = w.textureManager.texture!"missile";
    }
    
    void updateAi() pure nothrow 
    {
        auto player = world.player;
        auto playerDir = (player.pos - pos);
        mDir = wedge(dir, playerDir);
    }
    
    bool process()
    {
        if(mTicksRemaining > 0)
        {
            --mTicksRemaining;
        }
        else
        {
            mHealth = 0;
        }

        update!true(this);
        if(mHealth <= 0)
        {
            ExpandingFireProjectile proj;
            proj.pos = pos;
            proj.speed = speed;
            spawnProjectile(proj);
        }
        else if(mTicksRemaining % 2)
        {
            SmokeProjectile proj;
            proj.type = (mTicksRemaining >> 1) % 2;
            proj.pos = pos;
            proj.speed = speed - dir * (maxSpeed / 2);
            spawnProjectile(proj);
        }
        return mHealth > 0;
    }
    
    void draw(Renderer ren, in TransformMapper mapper)
    {
        Point pt;
        double dr;
        if(mapper.map(pos, dir, pt, dr))
        {
            mSprite.draw(ren, pt, dr);
        }
    }
}